import json
import os
import threading
import time

import cv2
import face_recognition
import pymysql
from django.http import HttpResponse

# 全局变量
record_saved = False


def send_http_response(response):
    """在单独的线程中发送HTTP响应"""
    return response


def face_image_recognition(request):
    # 打开摄像头
    capture = cv2.VideoCapture(0)
    # 标志变量，用于跟踪是否已经保存了记录
    global record_saved
    start_time = time.time()

    while True:
        ret, frame = capture.read()
        if not ret:
            print("无法从摄像头读取帧")
            break

        # 图像类型转换函数
        img_modi_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        try:
            # 将摄像头采集的一帧图像编码
            train_encode = face_recognition.face_encodings(img_modi_rgb)[0]

            # 返回face_images文件夹里面的内容（录入过的所有人的人脸）
            pathDir = os.listdir("D:/Django/Face_licensePlate_recognition_django/face_images")  # 返回的是文件夹里的每一张图片
            for i in pathDir:
                # 将文件夹里的每一张图片打开
                access = face_recognition.load_image_file(
                    "D:/Django/Face_licensePlate_recognition_django/face_images/" + i)
                access = cv2.cvtColor(access, cv2.COLOR_BGR2RGB)  # 图像类型转换函数
                access_encode = face_recognition.face_encodings(access)[0]

                # compare_faces比较脸部编码列表和候选编码，看看它们是否匹配
                matches = face_recognition.compare_faces([train_encode], access_encode, tolerance=0.45)
                if True in matches:
                    print(i + " 人脸认证通过!")
                    # 从文件名中提取登录人的ID
                    parts = i.split('-')
                    person_name = parts[0]
                    person_id = parts[1]

                    # 如果还没有保存记录，则保存记录
                    if not record_saved:
                        # 当认证成功,将人脸认证通过的ID传入保存记录的方法
                        result = saveFaceRecognitionPass(person_id, person_name)
                        '''
                        由于摄像头是一直在工作的，不停的在采集图像，一秒钟内要采集很多张，
                        如果不做处理，在一秒中内会存多条记录，实际场景中应该要做处理,
                        这里采用：当第一次认证成功，并且进出记录也存入数据库了，可以让程序暂停3秒
                        '''
                        if result:
                            print(f"记录保存成功，当前时间: {time.time() - start_time:.2f} 秒")
                            record_saved = True  # 设置标志变量为True

                            # 在单独的线程中发送HTTP响应
                            http_response = HttpResponse(
                                json.dumps({"code": 200, "msg": "认证成功", "data": "登录人的id: " + person_id}),
                                content_type='application/json'
                            )
                            threading.Thread(target=send_http_response, args=(http_response,)).start()

                            # 为了确保程序在暂停3秒后能够继续处理新的帧，在单独的线程中执行暂停
                            threading.Thread(target=sleep_and_reset, args=(3, start_time)).start()
                    else:
                        print(f"记录已保存，等待暂停时间结束，当前时间: {time.time() - start_time:.2f} 秒")
                else:
                    print("人脸验证失败")
        except IndexError as e:
            # 捕获未检测到人脸的异常
            print("未检测到人脸! " + str(e))
            continue  # 跳过当前迭代，继续下一次迭代
        except Exception as e:
            # 捕获其他异常
            print("发生错误: " + str(e))
            continue  # 跳过当前迭代，继续下一次迭代

        # 显示结果
        cv2.imshow('Video', frame)

        # 按'q'退出循环
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # 释放摄像头资源
    capture.release()
    cv2.destroyAllWindows()  # 正确关闭所有OpenCV窗口

    return HttpResponse(json.dumps({"code": 400, "msg": "未检测到有效人脸"}), content_type='application/json')


# 将人脸认证通过的，存入进出记录表
def saveFaceRecognitionPass(person_id, person_name):
    # 连接数据库
    con = pymysql.Connect(
        host="localhost",
        user="root",
        passwd="root",
        database="property_management_system",
        charset="utf8"
    )
    cursor = con.cursor()
    try:
        # 编写sql代码
        sql = "INSERT INTO person_access_records(householder_name, access_time, householder_id) VALUES (%s, NOW(), %s)"
        cursor.execute(sql, (person_name, person_id))
        # 返回受影响的行数
        num = cursor.rowcount
        result = False
        if num > 0:
            result = True
        # 提交事务
        con.commit()
    except Exception as e:
        # 如果有异常发生，回滚事务
        con.rollback()
        print(f"An error occurred: {e}")
        result = False
    finally:
        # 关闭游标
        cursor.close()
        # 关闭连接
        con.close()

    return result


def sleep_and_reset(seconds, start_time):
    """暂停指定秒数后，调用回调函数重置标志变量"""
    print(f"开始暂停，当前时间: {time.time() - start_time:.2f} 秒")
    time.sleep(seconds)
    print(f"暂停结束，当前时间: {time.time() - start_time:.2f} 秒")
    global record_saved
    record_saved = False